package com.tsunami.auth.service.auth.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tsunami.auth.mapper.ResourceMapper;
import com.tsunami.auth.service.auth.IResourceService;
import com.tsunami.auth.service.auth.IRoleAuthorityService;
import com.tsunami.auth.service.auth.IRoleService;
import com.tsunami.auth.service.auth.IUserService;
import com.tsunami.auth.utils.RedisUtils;
import com.tsunami.authority.dto.auth.ResourceQueryDTO;
import com.tsunami.authority.dto.auth.ResourceUpdateDTO;
import com.tsunami.authority.entity.auth.Resource;
import com.tsunami.authority.entity.auth.Role;
import com.tsunami.authority.entity.auth.RoleAuthority;
import com.tsunami.base.R;
import com.tsunami.common.AuthConstant;
import com.tsunami.exception.BizException;
import com.tsunami.exception.code.ExceptionCode;
import com.tsunami.user.model.SysUser;
import com.tsunami.utils.PageUtils;
import com.tsunami.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源表 服务实现类
 * </p>
 *
 * @author lx
 * @since 2021-09-23
 */
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements IResourceService {

    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IRoleAuthorityService roleAuthorityService;
    @Autowired
    private RedisUtils redisUtil;

    @Override
    public List<String> findVisibleResource(Long userId) {
        return baseMapper.findVisibleResource(userId);
    }

    @Override
    public List<Resource> findVisibleResource(ResourceQueryDTO resource) {
        List<Resource> visibleResource = baseMapper.findVisibleByResource(resource);
        return visibleResource;
    }

    @Override
    public R selectPageList(Resource data) {
        Page<Resource> pages = baseMapper.selectPageList(PageUtils.buildPage(),data);
        return R.ok().data(pages);
    }

    @Override
    public Resource updateResource(SysUser loginUser, ResourceUpdateDTO data) {
        Resource resource = getById(data.getId());
//        resource.setTenantId();
//        resource.setCode();
//        resource.setMethod();
//        resource.setUrl();

//        menu.setTenantId();
        if(StringUtils.isNotEmpty(data.getName())){
            resource.setName(data.getName());
        }
        if(StringUtils.isNotEmpty(data.getDescribe())){
            resource.setDescribe(data.getDescribe());
        }
        if(data.getMenuId()!= null){
            resource.setMenuId(data.getMenuId());
        }
        resource.setUpdateUser(loginUser.getId());
        super.updateById(resource);
        return resource;
    }

    @Override
    public List<Long> findMenuIdByResourceId(List<Long> resourceIdList) {
        return baseMapper.findMenuIdByResourceId(resourceIdList);
    }

    @Override
    public Map<String, Object> initResourceRolesMap() {
        Map<String,Object> resourceRoleMap = new TreeMap<>();
        QueryWrapper param = new QueryWrapper();
        param.isNotNull("code");
        List<Resource> resourceList = list(param);
        List<Role> roleList = roleService.findRolesByStatus("1");
        List<RoleAuthority> relation = roleAuthorityService.list();
        for(Resource resource: resourceList){
            Set<Long> roleIds = relation.stream()
                    .filter(item -> item.getAuthorityId().equals(resource.getId()))
                    .map(RoleAuthority::getRoleId).collect(Collectors.toSet());
            List<String> roleNames = roleList.stream()
                    .filter(item -> roleIds.contains(item.getId()))
                    .map(item -> item.getId()+"_"+item.getCode()).collect(Collectors.toList());
            resourceRoleMap.put("/"+resource.getServer()+resource.getUrl(),roleNames);
        }
        redisUtil.del(AuthConstant.RESOURCE_ROLES_MAP_KEY);
        redisUtil.hmset(AuthConstant.RESOURCE_ROLES_MAP_KEY,resourceRoleMap);
        return resourceRoleMap;
    }

    @Override
    public List<Resource> findResourceByMenu(Long menuId) {
        QueryWrapper param = new QueryWrapper<>();
        param.eq("menu_id",menuId);
        return super.list(param);
    }

    @Override
    public boolean save(Resource entity) {
        QueryWrapper param = new QueryWrapper<>();
        param.eq("code",entity.getCode());
        Resource resource = getOne(param);
        if(resource!=null){
            throw new BizException(ExceptionCode.HAVE_CODE);
        }
        super.save(resource);
        return true;
    }
}
